/*
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! CHECKER      Test check store and load by name
//! RUN          options: "--no-async-jit --compiler-hotness-threshold=10 --compiler-regex _GLOBAL::test_load_store_by_name.*", entry: "_GLOBAL::func_main_0"
//! METHOD       "test_load_store_by_name_single_field_inlined"
//! PASS_AFTER   "InlineIntrinsics"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    /StoreObject.*Dynamic/
//! INST_NEXT    /LoadObject.*Dynamic/
//! INST_NOT     "LoadArray"
//! INST_NOT     "StoreArray"
//! EVENT         /Compilation,_GLOBAL::test_load_store_by_name_single_field_inlined,.*,COMPILED/
//! METHOD       "test_load_store_by_name_single_field_properties"
//! PASS_AFTER   "InlineIntrinsics"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    /LoadObject.*Properties/
//! INST_NEXT    "StoreArray"
//! INST_NEXT    "LoadArray"
//! INST_NOT     "StoreObject"
//! EVENT         /Compilation,_GLOBAL::test_load_store_by_name_single_field_properties,.*,COMPILED/
//! METHOD       "test_load_store_by_name_single_transition_inlined"
//! PASS_AFTER   "InlineIntrinsics"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    /StoreObject.*Class/
//! INST_NEXT    /StoreObject.*Dynamic/
//! INST_NEXT    /LoadObject.*Dynamic/
//! INST_NOT     "LoadArray"
//! INST_NOT     "StoreArray"
//! EVENT         /Compilation,_GLOBAL::test_load_store_by_name_single_transition_inlined,.*,COMPILED/
//! METHOD       "test_load_store_by_name_single_transition_properties"
//! PASS_AFTER   "InlineIntrinsics"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    /LoadObject.*Properties/
//! INST_NEXT    "LenArray"
//! INST_NEXT    "BoundsCheck"
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    /StoreObject.*Class/
//! INST_NEXT    "StoreArray"
//! EVENT         /Compilation,_GLOBAL::test_load_store_by_name_single_transition_properties,.*,COMPILED/
//! METHOD       "test_load_store_by_name_single_prototype_inlined"
//! PASS_AFTER   "InlineIntrinsics"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "DeoptimizeIf"
//! INST_NEXT    "LoadObjFromConst"
//! INST_NEXT    /LoadObject.*Prototype holder/
//! INST_NEXT    /LoadObject.*Prototype cell/
//! INST_NEXT    /LoadObject.*IsChangeFieald/
//! INST_NEXT    "DeoptimizeIf"
//! EVENT         /Compilation,_GLOBAL::test_load_store_by_name_single_prototype_inlined,.*,COMPILED/
//! METHOD       "test_load_store_by_name_polymorphic"
//! PASS_AFTER   "InlineIntrinsics"
//! INST         "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE"
//! INST_NEXT    "CastAnyTypeValue"
//! INST_NEXT    /LoadObject.*Class/
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "LoadImmediate"
//! INST_NEXT    "Compare"
//! INST_NEXT    "IfImm"
//! INST_COUNT   "LoadObject", 5
//! INST_COUNT   "StoreArray", 1
//! INST_COUNT   "LoadArray", 1
//! INST_COUNT   "StoreObject", 1
//! EVENT         /Compilation,_GLOBAL::test_load_store_by_name_polymorphic,.*,COMPILED/
//! EVENT_NEXT    /DeoptimizationReason,.*test_load_store_by_name_single_field_inlined.*INLINE_IC/
//! EVENT_NEXT    /DeoptimizationReason,.*test_load_store_by_name_single_transition_inlined.*INLINE_IC/
//! EVENT_NEXT    /DeoptimizationReason,.*test_load_store_by_name_single_field_properties.*ANY_TYPE_CHECK/
//! EVENT_NEXT    /DeoptimizationReason,.*test_load_store_by_name_single_prototype_inlined.*ANY_TYPE_CHECK/


function Test() {}
Test.prototype.field1 = 5;
Test.prototype.field2 = 4;

function test_load_store_by_name_single_field_inlined(a) {
    a.field1 = 2
    return a.field2
}

function test_load_store_by_name_single_field_properties(a) {
    a.field1 = 5
    return a.field3
}

function test_load_store_by_name_polymorphic(a) {
    a.field1 = 10
    return a.field2
}

function test_load_store_by_name_single_transition_inlined(a) {
    a.field2 = 3
    return a.field1
}

function test_load_store_by_name_single_transition_properties(a) {
    a.field200 = 5
    return a.field1
}

function test_load_store_by_name_single_prototype_inlined(a) {
    return a.field1
}

let a = {}
a.field1 = 5
a.field2 = 8

for (let i = 0 ; i < 50; i++) {
    if (test_load_store_by_name_single_field_inlined(a) != 8) {
        throw "test_load_store_by_name_single_field_inlined is failed for inlined case - incorrect return value";
    }
    if (a.field1 != 2) {
        throw "test_load_store_by_name_single_field_inlined is failed for inlined case - incorrect load value";
    }
}
let b = {}
for (let i = 100 ; i >=0 ; --i) {
    b["field" + i] = i
}

for (let i = 0 ; i < 50; i++) {
    if (test_load_store_by_name_single_field_properties(b) != 3) {
        throw "test_load_store_by_name_single_field_properties is failed - incorrect return value";
    }
    if (b.field1 != 5) {
        throw "test_load_store_by_name_single_field_properties is failed - incorrect load value";
    }
}

for (let i = 0 ; i < 50; i++) {
    if (test_load_store_by_name_polymorphic(a) != 8) {
        throw "test_load_store_by_name_polymorphic is failed - incorrect return value for a";
    }
    if (a.field1 != 10) {
        throw "test_load_store_by_name_polymorphic is failed - incorrect load value for a";
    }
    if (test_load_store_by_name_polymorphic(b) != 2) {
        throw "test_load_store_by_name_polymorphic is failed - incorrect return value for b";
    }
    if (b.field1 != 10) {
        throw "test_load_store_by_name_polymorphic is failed - incorrect load value for b";
    }
}

for (let i = 0 ; i < 50; i++) {
    let c = {};
    c.field1 = i
    if (test_load_store_by_name_single_transition_inlined(c) != i) {
        throw "test_load_store_by_name_single_transition_inlined is failed for inlined case - incorrect return value";
    }
    if (c.field2 != 3) {
        throw "test_load_store_by_name_single_transition_inlined is failed for inlined case - incorrect load value";
    }
}

for (let i = 0 ; i < 50; i++) {
    let k = {};
    for (let j = 0 ; j < 98; ++j) {
        k["field" + j] = j
    }
    if (test_load_store_by_name_single_transition_properties(k) != 1) {
        throw "test_load_store_by_name_single_transition_properties is failed  - incorrect return value";
    }
    if (k.field200 != 5) {
        throw "test_load_store_by_name_single_transition_properties is failed  - incorrect load value";
    }
}

var prot = new Test()

for (let i = 0 ; i < 50; i++) {
    if (test_load_store_by_name_single_prototype_inlined(prot) != 5) {
        throw "test_load_store_by_name_single_prototype_inlined is failed  - incorrect return value";
    }
}

test_load_store_by_name_single_field_inlined(b)

let d = {};
d.field1 = 0
d.field3 = 0
test_load_store_by_name_single_transition_inlined(d)

var get_type_error = false;
try {
    test_load_store_by_name_single_field_properties(10)
} catch (e) {
    if (e instanceof TypeError) {
        get_type_error = true;
    }
}
if (!get_type_error) {
    throw "don't catch type error";
}

var get_type_error_2 = false;
try {
    test_load_store_by_name_single_prototype_inlined(undefined)
} catch (e) {
    if (e instanceof TypeError) {
        get_type_error_2 = true;
    }
}
if (!get_type_error_2) {
    throw "don't catch type error 2";
}